package craky.componentc;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;

import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSpinnerUI;

import craky.util.UIResourceManager;
import craky.util.UIUtil;

public class CSpinnerUI extends BasicSpinnerUI
{
    private static final Color DISABLED_BG = UIResourceManager.getColor(UIResourceManager.KEY_TEXT_DISABLED_BACKGROUND);
    
    private LayoutManager layout;
    
    public static ComponentUI createUI(JComponent c)
    {
        return new CSpinnerUI();
    }

    protected Component createPreviousButton()
    {
        JCButton button = new JCButton();
        button.setPreferredSize(new Dimension(20, -1));
        button.setRequestFocusEnabled(false);
        installPreviousButtonListeners(button);
        button.setImage(UIResourceManager.getImage(UIResourceManager.KEY_SPINNER_PREVIOUS_IMAGE));
        button.setPressedImage(UIResourceManager.getImage(UIResourceManager.KEY_SPINNER_PREVIOUS_PRESSED_IMAGE));
        button.setRolloverImage(UIResourceManager.getImage(UIResourceManager.KEY_SPINNER_PREVIOUS_ROLLOVER_IMAGE));
        button.setDisabledImage(UIResourceManager.getImage(UIResourceManager.KEY_SPINNER_PREVIOUS_DISABLED_IMAGE));
        button.setIcon(UIResourceManager.getIcon(UIResourceManager.KEY_SPINNER_PREVIOUS_ICON));
        button.setDisabledIcon(UIResourceManager.getIcon(UIResourceManager.KEY_SPINNER_PREVIOUS_DISABLED_ICON));
        button.setImageInsets(2, 2, 2, 2);
        return button;
    }

    protected Component createNextButton()
    {
        JCButton button = new JCButton();
        button.setPreferredSize(new Dimension(20, -1));
        button.setRequestFocusEnabled(false);
        installNextButtonListeners(button);
        button.setImage(UIResourceManager.getImage(UIResourceManager.KEY_SPINNER_NEXT_IMAGE));
        button.setPressedImage(UIResourceManager.getImage(UIResourceManager.KEY_SPINNER_NEXT_PRESSED_IMAGE));
        button.setRolloverImage(UIResourceManager.getImage(UIResourceManager.KEY_SPINNER_NEXT_ROLLOVER_IMAGE));
        button.setDisabledImage(UIResourceManager.getImage(UIResourceManager.KEY_SPINNER_NEXT_DISABLED_IMAGE));
        button.setIcon(UIResourceManager.getIcon(UIResourceManager.KEY_SPINNER_NEXT_ICON));
        button.setDisabledIcon(UIResourceManager.getIcon(UIResourceManager.KEY_SPINNER_NEXT_DISABLED_ICON));
        button.setImageInsets(2, 2, 2, 2);
        return button;
    }
    
    public void update(Graphics g, JComponent c)
    {
        paintBackground(g, c);
        super.update(g, c);
    }
    
    private void paintBackground(Graphics g, JComponent c)
    {
        if(c instanceof JCSpinner)
        {
            JCSpinner spinner = (JCSpinner)c;
            UIUtil.paintBackground(g, spinner, spinner.getBackground(), DISABLED_BG, spinner.getImage(),
                            spinner.isImageOnly(), spinner.getAlpha(), spinner.getVisibleInsets());
        }
    }
    
    protected LayoutManager createLayout()
    {
        if(layout == null)
        {
            layout = new SpinnerUILayout();
        }
        
        return layout;
    }
    
    protected void installDefaults()
    {
        spinner.setLayout(createLayout());
    }
    
    protected void uninstallDefaults()
    {}
    
    private class SpinnerUILayout implements LayoutManager
    {
        private final Dimension ZERO_SIZE = new Dimension(0, 0);

        private Component nextButton;

        private Component previousButton;

        private Component editor;

        public void addLayoutComponent(String name, Component c)
        {
            if("Next".equals(name))
            {
                nextButton = c;
            }
            else if("Previous".equals(name))
            {
                previousButton = c;
            }
            else if("Editor".equals(name))
            {
                editor = c;
            }
        }

        public void removeLayoutComponent(Component c)
        {
            if(c == nextButton)
            {
                nextButton = null;
            }
            else if(c == previousButton)
            {
                previousButton = null;
            }
            else if(c == editor)
            {
                editor = null;
            }
        }

        private Dimension preferredSize(Component c)
        {
            return (c == null)? ZERO_SIZE: c.getPreferredSize();
        }

        public Dimension preferredLayoutSize(Container parent)
        {
            Dimension nextD = preferredSize(nextButton);
            Dimension previousD = preferredSize(previousButton);
            Dimension editorD = preferredSize(editor);
            editorD.height = ((editorD.height + 1) / 2) * 2;
            Dimension size = new Dimension(editorD.width, editorD.height);
            size.width += Math.max(nextD.width, previousD.width);
            Insets insets = parent.getInsets();
            size.width += insets.left + insets.right;
            size.height += insets.top + insets.bottom;
            return size;
        }

        public Dimension minimumLayoutSize(Container parent)
        {
            return preferredLayoutSize(parent);
        }

        private void setBounds(Component c, int x, int y, int width, int height)
        {
            if(c != null)
            {
                c.setBounds(x, y, width, height);
            }
        }

        public void layoutContainer(Container parent)
        {
            int width = parent.getWidth();
            int height = parent.getHeight();
            Insets insets = parent.getInsets();
            Dimension nextD = preferredSize(nextButton);
            Dimension previousD = preferredSize(previousButton);
            int buttonsWidth = Math.max(nextD.width, previousD.width);
            int editorHeight = height - (insets.top + insets.bottom);
            int editorX, editorWidth, buttonsX;
            
            if(parent.getComponentOrientation().isLeftToRight())
            {
                editorX = insets.left;
                editorWidth = width - buttonsWidth - insets.left - insets.right;
                buttonsX = width - buttonsWidth - insets.right;
            }
            else
            {
                buttonsX = insets.left;
                editorX = buttonsX + buttonsWidth;
                editorWidth = width - buttonsWidth - insets.left - insets.right;
            }

            int nextY = insets.top;
            int nextHeight = editorHeight / 2;
            int previousY = insets.top + nextHeight + editorHeight % 2;
            int previousHeight = height - previousY - insets.bottom;
            
            setBounds(editor, editorX, insets.top, editorWidth, editorHeight);
            setBounds(nextButton, buttonsX, nextY, buttonsWidth, nextHeight);
            setBounds(previousButton, buttonsX, previousY, buttonsWidth, previousHeight);
        }
    }
}